package com.canaan.common.encrypt;

import cn.hutool.core.lang.Pair;
import cn.hutool.core.lang.TypeReference;
import cn.hutool.json.JSONUtil;
import com.alibaba.druid.support.json.JSONUtils;
import com.alibaba.fastjson2.JSON;
import com.canaan.common.enums.BusinessStatus;
import com.canaan.framework.manager.AsyncManager;
import com.canaan.framework.manager.factory.AsyncFactory;
import com.canaan.system.domain.ApiLog;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.utils.Lists;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.message.BasicNameValuePair;

import java.net.InetAddress;
import java.util.List;
import java.util.SortedMap;
import java.util.TreeMap;

/**
 * 这个类是调用edi封装，需要处理成工具类，移除对HttpCallback的强制依赖
 *
 * @author zjx
 * @Description 推送管理
 * @since 2023/10/27 19:47
 */
@Slf4j
public class PushEdiService {

    private static final String FAIL = "fail";

    /**
     * 发送Http请求
     *
     * @param url     url
     * @param content 内容 json
     * @return
     */
    public static Pair<Boolean, String> push(String url, String content) {
        if (StringUtils.isBlank(url)) {
            log.error("url is empty");
            return Pair.of(Boolean.FALSE, "url is empty");
        }
        ApiLog apiLog = new ApiLog();
        try {
            // *========数据库日志=========*//
            apiLog.setTitle("EDI 推送");
            apiLog.setStatus(BusinessStatus.SUCCESS.ordinal());
            apiLog.setOperUrl(url);
            apiLog.setOperParam(content);
            String ipAddress = InetAddress.getLocalHost().getHostAddress();
            apiLog.setOperIp(ipAddress);


            PushReqParam<String> param = new PushReqParam<>();
            param.setData(content);
            String jq = AesCryptorUtils.encrypt(JSON.toJSONString(param), AesCryptorUtils.SECURITY_KEY);
            SortedMap<String, String> params = new TreeMap<>();
            params.put("cid", AesCryptorUtils.CID);
            params.put("q", jq);
            String sign = SignUtils.doMd5Sign(SignUtils.getSignStr(params) + AesCryptorUtils.SECURITY_KEY);
            List<BasicNameValuePair> paramsList = getBasicNameValuePairs(AesCryptorUtils.CID, jq, sign);

            log.info("PushService.paramsList,paramsList:{}, content:{}", JSON.toJSONString(paramsList), content);
            String result = HttpClientUtils.post(url, paramsList);
            log.info("PushService.result:{}", result);
            String decResult = AesCryptorUtils.decrypt(result, AesCryptorUtils.SECURITY_KEY);
            boolean b = handleResult(decResult);
            if (StringUtils.isNotEmpty(decResult) && !b) {
//                AlarmUtil.sendAlarm("调用CT失败:" + JSON.toJSONString(param), decResult);
                log.error("调用CT失败,decResult:{},paramsList:{}, content:{}", decResult, paramsList, content);
                throw new Exception("调用CT失败:" + decResult);
            }
            apiLog.setJsonResult(decResult);
            return Pair.of(Boolean.TRUE, decResult);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            apiLog.setJsonResult(e.getMessage());
            return Pair.of(Boolean.FALSE, e.getMessage());
        }finally {
            // 保存数据库
            AsyncManager.me().execute(AsyncFactory.recordApiLog(apiLog));
        }
    }


    /**
     * 处理结果转换
     *
     * @param jsonStr json
     * @return true推送成功, false推送失败
     */
    private static boolean handleResult(String jsonStr) {
        ApiResult apiResult = JSONUtil.toBean(jsonStr, ApiResult.class);
        ResultDTO<Object> result = JSONUtil.toBean(apiResult.getContent().toString(), new TypeReference<ResultDTO>() {
        }, true);
        return !FAIL.equalsIgnoreCase(result.getStatus());
    }

    private static List<BasicNameValuePair> getBasicNameValuePairs(String cid, String jq, String sign) {
        List<BasicNameValuePair> paramsList = Lists.newArrayList();
        paramsList.add(new BasicNameValuePair("q", jq));
        paramsList.add(new BasicNameValuePair("cid", cid));
        paramsList.add(new BasicNameValuePair("sign", sign));
        return paramsList;
    }
}
